package com.group4.blockchain.smartcontract;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.hyperledger.fabric.contract.Context;
import org.hyperledger.fabric.contract.ContractInterface;
import org.hyperledger.fabric.contract.annotation.*;
import org.hyperledger.fabric.shim.ChaincodeException;
import org.hyperledger.fabric.shim.ChaincodeStub;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Class: Contract
 */
@Contract(
        name = "buyer.Contract",
        info = @Info(
                title = "Contract",
                description = "SmartContract",
                version = "1.0.0",
                license = @License(
                        name = "Apache 2.0 License",
                        url = "http://www.apache.org/licenses/LICENSE-2.0.html"),
                contact = @Contact(
                        email = "10690925080@qq.com",
                        name = "Group4"
                )
        )
)
@Default
public final class MyContract implements ContractInterface {
    enum Message {
        NUM_EXCEED("num exceed"),
        LIST_NOT_EXIST("List '%s' not exist"),
        BUYING_NOT_EXIST("this buying order '%s' not exist"),
        BUYERLIST_NOT_EXISTING("Buyer List '%s' does not exist."),
        LIST_STATE_ERROR("This '%s' List state is error now."),
        LIST_TIMEOUT("This '%s' List is timeout"),
        ARG_NUM_WRONG("Incorrect number of arguments '%s'"),
        USER_NOT_EXISTING("User '%s' does not exist."),
        BUYING_NOT_SUCCESS("this buying order '%s' not success"),
        Transaction_ERROR("Buying order '%s' not belong to Lists '%s'"),
        Transaction_NOT_EXIST("this transaction '%s' not exist");

        private String tmpl;

        private Message(String tmpl) {
            this.tmpl = tmpl;
        }

        public String template() {
            return this.tmpl;
        }
    }


    /**
     * 测试初始化
     * InitChainCode function
     * @param ctx Context
     */
    @Transaction(name = "InitChainCode", intent = Transaction.TYPE.SUBMIT)
    public void initChainCode(final Context ctx) {
        ChaincodeStub stub = ctx.getStub();
        stub.putStringState("ID", "THE LOWER PRICE TRANSACTION PLATFORM");
        stub.putStringState("platformMoney","0");
        //存放所有商品清单id
        List<String> list = new ArrayList<>();
        stub.putStringState("allSellerCards",JSON.toJSONString(list));
        //存放所有交易成功的交易id
        stub.putStringState("allTransIDs", JSON.toJSONString(list));
    }


    /**
     * 添加心愿卡
     * AddBuyerCard function
     * @param ctx Context
     * @param buyerID String
     * @param buyerCardID String
     * @param goodName String
     * @param buyerPrice String
     */
    @Transaction(name = "AddBuyerCard", intent = Transaction.TYPE.SUBMIT)
    public String addBuyerCard(final Context ctx, final String buyerID, final String buyerCardID, final String goodName, final String buyerPrice) {
        ChaincodeStub stub = ctx.getStub();
        Map<String, String> map = new HashMap<>();
        map.put("buyerCardID", buyerCardID);
        map.put("buyerID", buyerID);
        map.put("goodName", goodName);
        map.put("buyerPrice", buyerPrice);
        map.put("listState", "1");   //"0"为关闭状态 "1"为开放状态  初始化状态为1
//        map.put("endTime", "0");    //初始化时长为0
        map.put("orderNum", "0");  ///符合条件的SellerListID个数
        map.put("orderIDs", "");   //符合条件的SellerListID
        //初始化（新建订单）
        stub.putStringState(buyerCardID, JSON.toJSONString(map));
        //获取用户所有的心愿卡,并增加这个心愿卡
        String allBuyCards = stub.getStringState(buyerID + "allCards");
        if (allBuyCards.isEmpty()){
            List<String> list = new ArrayList<>();
            list.add(buyerCardID);
            stub.putStringState(buyerID + "allCards",JSON.toJSONString(list));
        }else {
            List list = JSON.parseObject(allBuyCards, List.class);
            list.add(buyerCardID);
            stub.putStringState(buyerID + "allCards",JSON.toJSONString(list));
        }
        return "ok";
    }

    /**
     * 通过key查询任意内容
     * QueryAny function
     * @param ctx context
     * @param key String
     */
    @Transaction(name = "QueryAny", intent = Transaction.TYPE.EVALUATE)
    public String queryAny(final Context ctx, final String key){
        ChaincodeStub stub = ctx.getStub();
        //有就返回内容，没有就是null
        return stub.getStringState(key);
    }

    /**
     * 关闭心愿卡或清单
     * Close function
     * @param ctx Context
     * @param cardID String
     */
    @Transaction(name = "Close", intent = Transaction.TYPE.SUBMIT)
    public String close(final Context ctx, final String cardID) {
        ChaincodeStub stub = ctx.getStub();
        JSONObject card = JSONObject.parseObject(stub.getStringState(cardID));

        // 愿望清单不存在
        if (card.isEmpty()) {
            String errorMessage = String.format(Message.BUYERLIST_NOT_EXISTING.template(), cardID);
            return errorMessage;
        }
        //查询当前愿望清单的状态
        String ListState = card.getString("listState");
        if (Integer.parseInt(ListState) == 0) {
            String errorMessage = String.format(Message.LIST_STATE_ERROR.template(), ListState);
            return errorMessage;
        } else {
            card.put("listState", "0");
            stub.putStringState(cardID, JSON.toJSONString(card));
            return "close successfully";
        }
    }

    /**
     * 初始化用户金额
     * InitMoney function
     * @param ctx context
     * @param userID String
     */
    //用户初始化 余额
    @Transaction(name = "InitMoney", intent = Transaction.TYPE.SUBMIT)
    public String initMoney(final Context ctx, final String userID) {
        ChaincodeStub stub = ctx.getStub();
        stub.putStringState(userID + "Money", "0");
        return "ok";
    }

    /**
     * 增加余额
     * Recharge function
     * @param ctx context
     * @param buyerID String
     * @param changeValue String
     */
    @Transaction(name = "Recharge", intent = Transaction.TYPE.SUBMIT)
    public String recharge(final Context ctx, final String buyerID, final String changeValue) {
        ChaincodeStub stub = ctx.getStub();
        String oldMoney = stub.getStringState(buyerID + "Money");
        try {
            Double.parseDouble(changeValue);
        } catch (Exception e) {
            String errorMessage = String.format(Message.ARG_NUM_WRONG.template(), changeValue);
            return errorMessage;
        }

        if (Double.parseDouble(changeValue) < 0) {
            return "金额为负";
//            stub.putStringState(buyerID + "Money", String.valueOf(0));
        }
        double newMoney = Double.parseDouble(oldMoney) + Double.parseDouble(changeValue);
        stub.putStringState(buyerID + "Money", String.valueOf(newMoney));
        return String.valueOf(newMoney);
    }


    /**
     * 用于遍历 是否 找到符合条件的清单id  并更新orderIDs
     * MatchSellerCards function
     * @param ctx context
     * @param buyerCardID String
     * @param sellerCardID String
     */
    @Transaction(name = "MatchSellerCards", intent = Transaction.TYPE.SUBMIT)
    public String matchSellerCards(final Context ctx, final String buyerCardID, final String sellerCardID) {
        ChaincodeStub stub = ctx.getStub();
        String buyerCardString = stub.getStringState(buyerCardID);
        if (buyerCardString.isEmpty()) {
            String errorMessage = String.format(Message.LIST_NOT_EXIST.template(), buyerCardID);
            return errorMessage;
        }
        JSONObject buyerCard = JSONObject.parseObject(buyerCardString);

        String sellerCardString = stub.getStringState(sellerCardID);
        if (sellerCardString.isEmpty()) {
            String errorMessage = String.format(Message.BUYING_NOT_EXIST.template(), sellerCardID);
            return errorMessage;
        }
        JSONObject sellerCard = JSONObject.parseObject(sellerCardString);

        //获取心愿单的价格
        String money = buyerCard.getString("buyerPrice");
        String orderIDs = buyerCard.getString("orderIDs");
        String listState = buyerCard.getString("listState");
        if (Integer.parseInt(listState)==0){
            return "";
        }
        //判断用户愿望清单和产品清单出价与售价大小
        if (sellerCard.getString("goodName").contains(buyerCard.getString("goodName"))) {    //当用户输入的产品名称被商家的产品名称包含时，认为用户需要此类产品
            if (Double.parseDouble(money) < Double.parseDouble(sellerCard.getString("sellerPrice"))) {
                String errorMessage = String.format(Message.BUYING_NOT_SUCCESS.template(), buyerCardID);
                return errorMessage;
            }

            if (orderIDs.equals("")) {
                buyerCard.put("orderIDs", sellerCardID);
            } else {
                buyerCard.put("orderIDs", orderIDs + "---" + sellerCardID);
            }
            String orderNum = buyerCard.getString("orderNum");
            buyerCard.put("orderNum", String.valueOf(Integer.parseInt(orderNum) + 1));

            //更新清单id
            stub.putStringState(buyerCardID,JSON.toJSONString(buyerCard));

            return "ok";
        } else {
            String errorMessage = String.format(Message.LIST_NOT_EXIST.template(), buyerCardID);
            return errorMessage;
        }
    }



    /**
     * 返回符合要求的清单id集合  orderIDs
     * MatchBestSellerCard function
     * @param ctx context
     * @param buyerCardID String
     */
    @Transaction(name = "MatchBestSellerCard", intent = Transaction.TYPE.EVALUATE)
    public String matchBestSellerCard(final Context ctx, final String buyerCardID) {
        ChaincodeStub stub = ctx.getStub();
        String buyerCardString = stub.getStringState(buyerCardID);
        if (buyerCardString.isEmpty()) {
            String errorMessage = String.format(Message.BUYING_NOT_EXIST.template(), buyerCardID);
            return errorMessage;
        }
        JSONObject buyerCard = JSONObject.parseObject(buyerCardString);
        String sellerIDS = buyerCard.getString("orderIDs");
        String[] selectID = sellerIDS.split("---");

        //寻找最小的价格
        double minPrice = Double.parseDouble(JSONObject.parseObject(stub.getStringState(selectID[0])).getString("sellerPrice"));
        for (int i = 0; i < selectID.length; i++) {
            double price = Double.parseDouble(JSONObject.parseObject(stub.getStringState(selectID[i])).getString("sellerPrice"));
            if (price < minPrice) {
                minPrice = price;
            }
        }
        //寻找价格为最小价格的sellerListID
        ArrayList<String> selectBestID = new ArrayList<>();
        for (int i = 0; i < selectID.length; i++) {
            if (Double.parseDouble(JSONObject.parseObject(stub.getStringState(selectID[i])).getString("sellerPrice")) == minPrice) {
                selectBestID.add(selectID[i]);
            }
        }

        //返回用到的清单id
        return JSON.toJSONString(selectBestID);
    }


    /**
     * 交易
     * DoTrans function
     * @param ctx context
     * @param buyerCardID String
     * @param sellerCardID String
     */
    @Transaction(name = "DoTrans", intent = Transaction.TYPE.SUBMIT)
    public String trans(final Context ctx, final String buyerCardID, final String sellerCardID) {
        ChaincodeStub stub = ctx.getStub();
        String buyerCardString = stub.getStringState(buyerCardID);
        if (buyerCardString.isEmpty()) {
            String errorMessage = String.format(Message.LIST_NOT_EXIST.template(), buyerCardID);
            return errorMessage;
        }
        JSONObject buyerCard = JSONObject.parseObject(buyerCardString);

        String sellerCardString = stub.getStringState(sellerCardID);
        if (sellerCardString.isEmpty()) {
            String errorMessage = String.format(Message.BUYING_NOT_EXIST.template(), sellerCardID);
            return errorMessage;
        }
        JSONObject sellerCard = JSONObject.parseObject(sellerCardString);


        //获取用户存款余额
        String buyerID = buyerCard.getString("buyerID");
        double money = Double.parseDouble(stub.getStringState(buyerID + "Money"));


        //判断用户愿望清单状态
        if (Integer.parseInt(buyerCard.getString("listState")) == 0) {
            String errorMessage = String.format(Message.LIST_STATE_ERROR.template(), buyerCardID);
            return errorMessage;
        } else {
//            Long initTime = System.currentTimeMillis();
            //判断愿望清单时限，如果当前时间大于终止时间，则无效
//            if (initTime > Long.valueOf(BuyerList.getString("endTime"))) {
//                String errorMessage = String.format(Message.LIST_TIMEOUT.template(), BuyerListID);
//                return errorMessage;
//            } else {
            buyerCard.put("orderNum", "0");
            buyerCard.put("orderIDs", "");

            //心愿单的价格
            double buyerPrice =  Double.parseDouble(buyerCard.getString("buyerPrice"));

            //商品价格
            double sellerPrice =  Double.parseDouble(sellerCard.getString("sellerPrice"));

            //差价
            double gapPrice = buyerPrice - sellerPrice;

            double buyerShouldPay = sellerPrice+0.45*gapPrice;
            double sellerShouldGet = buyerPrice-0.45*gapPrice;

            if ( money<buyerShouldPay){
                return "余额不足";
            }
            stub.putStringState(buyerID+"Money",String.valueOf(money-buyerShouldPay));
            String sellerID = sellerCard.getString("sellerID");
            double sellerMoney = Double.parseDouble(stub.getStringState(sellerID+"Money"));
            stub.putStringState(sellerID+"Money",String.valueOf(sellerMoney+sellerShouldGet));

            //平台获利
            String platformMoney = stub.getStringState("platformMoney");
            stub.putStringState("platformMoney",String.valueOf(Double.parseDouble(platformMoney)+gapPrice*0.1));
//            public String close(final Context ctx, final String BuyerListID) {
            //关闭心愿卡和商品清单
            close(ctx,buyerCardID);
            close(ctx,sellerCardID);
            Map<String, String> map = new HashMap<>();
            map.put("transID", buyerCardID + "-" + sellerCardID);
            map.put("buyerID", buyerID);
            map.put("sellerID", sellerID);
            map.put("buyerPay", String.valueOf(buyerShouldPay));
            map.put("sellerGet", String.valueOf(sellerShouldGet));
            map.put("platformProfit", String.valueOf(gapPrice*0.1));
            //创建交易单
            stub.putStringState(buyerCardID + "-" + sellerCardID, JSON.toJSONString(map));
            //将交易单ID存放到allTransIDs
            List allTransIDs = JSON.parseObject(stub.getStringState("allTransIDs"), List.class);
            allTransIDs.add(buyerCardID + "-" + sellerCardID);
            stub.putStringState("allTransIDs",JSON.toJSONString(allTransIDs));
            return "ok";
        }
    }




    /**
     * 创建商品清单
     * AddSellerCard function
     * @param ctx context
     * @param sellerID String
     * @param sellerCardID String
     * @param goodName String
     * @param sellerPrice String
     */
    @Transaction(name = "AddSellerCard", intent = Transaction.TYPE.SUBMIT)
    public String addSellerCard(final Context ctx, final String sellerID, final String sellerCardID, final String goodName, final String sellerPrice) {
        ChaincodeStub stub = ctx.getStub();
        Map<String, String> map = new HashMap<>();
        map.put("sellerCardID", sellerCardID);
        map.put("sellerID", sellerID);
        map.put("goodName", goodName);
        map.put("sellerPrice", sellerPrice);
        map.put("listState", "1");   //"0"为关闭状态 "1"为开放状态 ,状态为1
        //初始化（新建订单）
        stub.putStringState(sellerCardID, JSON.toJSONString(map));
        //添加到卖家商品清单集合
        String allSellerCards = stub.getStringState(sellerID + "allCards");
        if (allSellerCards.isEmpty()){
            List<String> list = new ArrayList<>();
            list.add(sellerCardID);
            stub.putStringState(sellerID + "allCards",JSON.toJSONString(list));
        }else {
            List list = JSON.parseObject(allSellerCards, List.class);
            list.add(sellerCardID);
            stub.putStringState(sellerID + "allCards",JSON.toJSONString(list));
        }
        //添加到总的商品清单
        List list1 = JSON.parseObject(stub.getStringState("allSellerCards"), List.class);
        list1.add(sellerCardID);
        stub.putStringState("allSellerCards",JSON.toJSONString(list1));
        return "ok";
    }

    /**
     * 查询状态
     * QueryState function
     * @param ctx         context
     * @param cardID
     * @return ListState and Residual time
     */
    @Transaction(name = "QueryState", intent = Transaction.TYPE.EVALUATE)
    public String queryState(final Context ctx, final String cardID) {
        ChaincodeStub stub = ctx.getStub();
        JSONObject card = JSONObject.parseObject(stub.getStringState(cardID));
        // 愿望清单不存在
        if (card==null) {
            String errorMessage = String.format(Message.BUYERLIST_NOT_EXISTING.template(), cardID);
            System.out.println(errorMessage);
            throw new ChaincodeException(errorMessage);
        }

        return card.getString("listState");
    }
    //    /**
//     * 用 QueryAny function即可
//     *
//     * 查询心愿卡或清单的各项详细内容
//     * QueryBuyerList function
//     * @param ctx Context
//     * @param BuyerListID String
//     * @param findKey String
//     */
//    @Transaction(name = "QueryBuyerList", intent = Transaction.TYPE.EVALUATE)
//    public String queryBuyerList(final Context ctx, final String BuyerListID, final String findKey) {
//        ChaincodeStub stub = ctx.getStub();
//        JSONObject BuyerList = JSONObject.parseObject(stub.getStringState(BuyerListID));
//
//        // 愿望清单不存在
//        if (BuyerList.isEmpty()) {
//            String errorMessage = String.format(Message.BUYERLIST_NOT_EXISTING.template(), BuyerListID);
//            System.out.println(errorMessage);
//            throw new ChaincodeException(errorMessage);
//        }
//        //查询已经满足要求的对应key上的某个值
//        String value = (String) BuyerList.get(findKey);
//        if (value.equals("")) {
//            return "输入的查询值为空";
//        } else {
//            return value;
//        }
//    }
//    //交易转账
//    @Transaction(name = "ReduceMoney", intent = Transaction.TYPE.SUBMIT)
//    public String reduceMoney(final Context ctx, final String buyerID, final String changeValue) {
//        ChaincodeStub stub = ctx.getStub();
//        String oldMoney = stub.getStringState(buyerID + "Money");
//        try {
//            Double.parseDouble(changeValue);
//        } catch (Exception e) {
//            String errorMessage = String.format(Message.ARG_NUM_WRONG.template(), changeValue);
//            return errorMessage;
//        }
//
//        if (Double.parseDouble(oldMoney) < Double.parseDouble(changeValue)) {
//            return  "余额不足";
////            stub.putStringState(buyerID + "Money", String.valueOf(0));
//        }
//
//        double newMoney = Double.parseDouble(oldMoney) - Double.parseDouble(changeValue);
//        stub.putStringState(buyerID + "Money", String.valueOf(newMoney));
//        return "ok";
//
//    }




//    /**
//     * 用 QueryAny function也可
//     *
//     * 查询能够满足清单价格的产品
//     * QuerySuitable_SellerListID function
//     * @param ctx context
//     * @param BuyerListID
//     * @return orderNum and orderIDs
//     */
//    @Transaction(name = "QuerySuitable_SellerListID", intent = Transaction.TYPE.EVALUATE)
//    public String querySuitable_SellerListID(final Context ctx, final String BuyerListID) {
//        ChaincodeStub stub = ctx.getStub();
//        JSONObject BuyerList = JSONObject.parseObject(stub.getStringState(BuyerListID));
//        // 愿望清单不存在
//        if (BuyerList.isEmpty()) {
//            String errorMessage = String.format(Message.BUYERLIST_NOT_EXISTING.template(), BuyerListID);
//            System.out.println(errorMessage);
//            throw new ChaincodeException(errorMessage);
//        }
//        //查询已经满足要求的SellerListID
//        String orderNum = (String) BuyerList.get("orderNum");
//        String orderIDs = (String) BuyerList.get("orderIDs");
//        if (Integer.parseInt(orderNum) == 0) {
//            return "目前没有价格低于此交易意愿的产品。";
//        } else {
//            return orderIDs;   //可以考虑交易的出售清单号
//        }
//    }







//    //改变交易状态，0代表支付待完成 1代表支付已完成 -1代表违约
//    @Transaction(name = "ChangeTrans", intent = Transaction.TYPE.SUBMIT)
//    public String changeTrans(final Context ctx, final String transID, final String transState) {
//        ChaincodeStub stub = ctx.getStub();
//        String transactionString = stub.getStringState(transID);
//        if (transactionString.isEmpty()) {
//            String errorMessage = String.format(Message.Transaction_NOT_EXIST.template(), transID);
//            return errorMessage;
//        }
//        JSONObject transaction = JSONObject.parseObject(transactionString);
//        transaction.put("transState", transState);
//        stub.putStringState(transID, JSON.toJSONString(transaction));
//        return "Change ok";
//    }

//    /**
//     * 查询交易状态
//     *
//     * @param ctx
//     * @param transID
//     * @return
//     */
//    @Transaction(name = "QueryTrans", intent = Transaction.TYPE.EVALUATE)
//    public String queryTrans(final Context ctx, final String transID) {
//        ChaincodeStub stub = ctx.getStub();
//        String transactionString = stub.getStringState(transID);
//        if (transactionString.isEmpty()) {
//            String errorMessage = String.format(Message.Transaction_NOT_EXIST.template(), transID);
//            return errorMessage;
//        }
//        JSONObject transaction = JSONObject.parseObject(transactionString);
//        String state = "";
//        switch (transaction.getString("transState")) {
//            case "0":
//                state = "支付待完成";
//                break;
//            case "1":
//                state = "支付已完成";
//                break;
//            case "-1":
//                state = "用户已违约";
//                break;
//        }
//        return state;  //交易状态
//    }

//    /**
//     * 用户余额查询
//     */
//    @Transaction(name = "QueryMoney", intent = Transaction.TYPE.EVALUATE)
//    public String queryMoney(final Context ctx, final String BuyerID) {
//        ChaincodeStub stub = ctx.getStub();
//        String value = stub.getStringState(BuyerID + "Money");
//        if (value.isEmpty()) {
//            String errorMessage = String.format(Message.USER_NOT_EXISTING.template(), BuyerID);
//            return errorMessage;
//        }
//        return value; //钱包余额
//    }

///**
// * Open function
// * @param ctx context
// * @param ListID
// * @param duration
// */
//
// @Transaction(name = "Open", intent = Transaction.TYPE.SUBMIT)
// public String open(final Context ctx, final String ListID, final String duration) {
// ChaincodeStub stub = ctx.getStub();
// JSONObject List = JSONObject.parseObject(stub.getStringState(ListID));
// List.put("duration", Integer.parseInt(duration) * 3600);    //用户输入时长单位为分钟
// Long startTime = System.currentTimeMillis();
// // 用户愿望清单不存在
// if (List.isEmpty()) {
// String errorMessage = String.format(Message.DISCOUNTRULE_NOT_EXISTING.template(), ListID);
// return errorMessage;
// }
// //查询当前用户愿望清单的状态
// String ListState = List.getString("ListState");
// if (Integer.parseInt(ListState) == 1) {
// String errorMessage = String.format(Message.RULE_STATE_ERROR.template(), ListState);
// return errorMessage;
// } else {
// String endTime = String.valueOf(startTime + Long.valueOf(duration)*3600);
// List.put("startTime", startTime);
// List.put("endTime", endTime);
// List.put("ruleState", "1");
// stub.putStringState(ListID,JSON.toJSONString(List));
// return "ok";
// }
// }


 }